﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using DACU.Player.Enums;
using DACU.Tools;
using DACU.Tools.JavaScript;
using DACU.VkontakteApi.Base;
//using TagLib;
using TagLib;
using Un4seen.Bass.AddOn.Tags;

namespace DACU.Player
{
	public class Track : IEquatable<Track>, IComparer<Track>, INotifyPropertyChanged, IComparable 
	{
		public event PropertyChangedEventHandler PropertyChanged;

		private TrackType _type;
		public TrackType Type
		{
			get { return _type; }
			set
			{
				_type = value;
				ChangeProperty("Type");
			}
		}

		private string _path;
		public string Path
		{
			get { return _path; }
			set
			{
				_path = value;
				ChangeProperty("Path");
			}
		}

		private string _artist;
		public string Artist
		{
			get { return _artist; }
			set
			{
				_artist = value;
				ChangeProperty("Artist");
			}
		}

		private string _title;
		public string Title
		{
			get { return _title; }
			set
			{
				_title = value;
				ChangeProperty("Title");
			}
		}

		private bool _enabled = true;
		public bool Enabled
		{
			get { return _enabled; }
			set
			{
				_enabled = value;
				ChangeProperty("Enabled");
			}
		}

		private bool _isCurrentlyPlays;
		public bool IsCurrentlyPlays
		{
			get { return _isCurrentlyPlays; }
			set
			{
				_isCurrentlyPlays = value;
				ChangeProperty("IsCurrentlyPlays");
			}
		}

		private TimeSpan _duration = TimeSpan.Zero;
		public TimeSpan Duration
		{
			get { return _duration; }
			set
			{
				_duration = TimeSpan.FromMilliseconds(value.TotalMilliseconds - value.Milliseconds);
				ChangeProperty("Duration");
			}
		}

		private double _seconds = double.NaN;
		public double Seconds
		{
			get { return _seconds; }
			set
			{
				_seconds = Math.Floor(value);
				ChangeProperty("Seconds");
			}
		}

		private object _source;
		public object Source
		{
			get { return _source; }
			set
			{
				_source = value;
				ChangeProperty("Source");
			}
		}

		private int _vKid;
		public int VKid
		{
			get { return _vKid; }
			set
			{
				_vKid = value;
				ChangeProperty("VKid");
			}
		}

		public bool IsEmpty
		{
			get
			{
				if (String.IsNullOrWhiteSpace(Path))
					if (Source == null)
						return true;
				return false;
			}
		}

		public Track()
		{
		}

		public Track(string path,TrackType type)
		{
			Path = path;
			Type = type;
		}

		//public static VKAudio ParsePlaylistString(string line)
		//{
		//    if (String.IsNullOrWhiteSpace(line)) return new VKAudio();
		//    string[] entry = line.Split('|');
		//    if (entry.Length <= 5) return new VKAudio();
		//    var audio = new VKAudio
		//                    {
		//                        Id = entry[0],
		//                        Url = entry[1],
		//                        Artist = entry[2].Trim(),
		//                        Title = entry[3].Trim(),
		//                        LyricsId = entry[4],
		//                        Duration = entry[5]
		//                    };
		//    return audio;
		//}

		public static Track FromJson(string json)
		{
			if(String.IsNullOrWhiteSpace(json))
				throw new ArgumentNullException("json");
			var data = Utils.JsonToData(json) as Dictionary<string, object>;
			var track = new Track();
			object value;
			if (data != null)
			{
				if (data.TryGetValue("A", out value))
					track.Artist = value == null ? "" : value.ToString();
				if (data.TryGetValue("N", out value))
					track.Title = value == null ? "" : value.ToString();
				if (data.TryGetValue("P", out value))
					track.Path = value == null ? "" : value.ToString();
				if (data.TryGetValue("E", out value))
					track.Enabled = value == null ? true : Convert.ToBoolean(value);
				if (data.TryGetValue("S", out value))
					track.Seconds = value == null ? 0 : Convert.ToDouble(value);
				if (data.TryGetValue("T", out value))
					track.Type = value == null ? TrackType.None : (TrackType)Enum.Parse(typeof(TrackType),value.ToString());
				if (data.TryGetValue("I", out value))
					track.VKid = value == null ? 0 : Convert.ToInt32(value);
				if (track.Seconds > 0)
					track.Duration = TimeSpan.FromSeconds(track.Seconds);
			}
			return track;
		}

		public string ToJson()
		{
			return @"{{A:""{0}"",N:""{1}"",P:""{2}"",E:{3},S:{4},T:{5}{6}}}".FormatStr(
				JavaScriptString.QuoteString(Artist),
				JavaScriptString.QuoteString(Title),
				JavaScriptString.QuoteString(Path),
				Enabled ? 1 : 0,
				Seconds.ToString().Replace(",","."),
				Type.ToString("d"),
				Type == TrackType.VKontakte ? ",I:" + VKid : ""
				);
		}

		public static Track FromVKAudio(VKAudio audio)
		{
			if(audio==null || audio.IsEmpty)
				throw new ArgumentNullException("audio");
			var track = new Track
			            	{
			            		Artist = audio.Artist,
			            		Path = audio.Url,
			            		Type = TrackType.VKontakte,
			            		Source = audio,
			            		Title = audio.Title
			            	};
			double duration;
			int id;
			if (double.TryParse(audio.Duration, out duration))
				track.Seconds = duration;
			track.Duration = TimeSpan.FromSeconds(track.Seconds);
			if (int.TryParse(audio.Id, out id))
				track.VKid = id;
			return track;
		}

		public bool Equals(Track other)
		{
			if (Type != other.Type ||
				(Path??"").GetHashCode() != (other.Path??"").GetHashCode() ||
				(Artist??"").GetHashCode() != (other.Artist??"").GetHashCode() ||
				(Title??"").GetHashCode() != (other.Title??"").GetHashCode()
				)
				return false;
			return true;
		}

		public int Compare(Track x, Track y)
		{
			if (x == null)
				return y == null ? 0 : -1;
			string xTitle = x.Artist + " " + x.Title;
			if (y == null) return 1;
			string yTitle = y.Artist + " " + y.Title;
			if (String.IsNullOrEmpty(xTitle))
				return String.IsNullOrEmpty(yTitle) ? 0 : -1;
			return String.IsNullOrEmpty(yTitle) ? 1 : xTitle.CompareTo(yTitle);
		}

		void ChangeProperty(string propertyName)
		{
			if(PropertyChanged!=null)
				PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
		}

		public override bool Equals(object obj)
		{
			return obj is Track ? Equals(obj as Track) : false;
		}

		public override int GetHashCode()
		{
			return Type.GetHashCode() + (Artist??"").GetHashCode() + (Title??"").GetHashCode();
		}

		public int CompareTo(object obj)
		{
			return Compare(this, obj as Track);
		}

		public override string ToString()
		{
			return Type + " | " + Artist + " | " + Title + (Type==TrackType.VKontakte?" | "+VKid:"");
		}

		public void GetInfoFromFile()
		{
			if (Type == TrackType.File)
			{
				/*TAG_INFO tag = BassTags.BASS_TAG_GetFromFile(Path);
				if(tag!=null)
				{
					Artist = tag.artist;
					Title = tag.title;
					Seconds = tag.duration;
					Duration = TimeSpan.FromSeconds(Seconds);
				}*/
				ByteVector.UseBrokenLatin1Behavior = true;
				TagLib.File file = TagLib.File.Create(Path);
				if (file != null)
				{
					Artist = file.Tag.FirstPerformer;
					Title = file.Tag.Title;
					Seconds = file.Properties.Duration.TotalSeconds;
					Duration = file.Properties.Duration;
					file.Dispose();
				}
				if (String.IsNullOrEmpty(Artist) && String.IsNullOrEmpty(Title))
					Title = System.IO.Path.GetFileNameWithoutExtension(Path);
			}
		}
	}
}
